package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

func main() {
	contextCancelTest()

	/*
	var wg sync.WaitGroup
	t1 := time.Now()
	ctx, _ := context.WithTimeout(context.Background(), 2*time.Second)
	wg.Add(1)
	go func() {
		ip, err := getIP(ctx, &wg)
		fmt.Println(ip, err)
	}()
	wg.Wait()
	fmt.Println(time.Since(t1))
	*/
}


// 模拟控制超时的情况，
// 我们在 1 秒后主动发送取消信号，
func contextCancelTest() {
	var wg sync.WaitGroup
	wg.Add(1)

	// 定义了一个有取消功能的 Context，
	// ctx 里面的 Done() 方法返回的 chan 在我们调用
	// cancel 方法的时候会获取到值。
	ctx, cancel := context.WithCancel(context.TODO())
	go func(c context.Context) {
		// 1 秒后发送取消信号
		time.Sleep(time.Second)
		cancel()
	}(ctx)

	// out 表示接收业务处理结果的 chan
	// 我们在业务处理完毕之后往其中写入数据
	out := make(chan struct{}, 1)
	go func(out chan struct{}) {
		// 模拟耗时 2 秒的业务处理
		time.Sleep(time.Second * 2)
		out <- struct{}{}
	}(out)

	select {
	case <-ctx.Done(): // 1 秒后，这里接收到值，执行这一个分支
		fmt.Println(ctx.Err()) // 输出：context canceled
		wg.Done()
	case <-out:
		fmt.Println("done!")
		wg.Done()
	}

	wg.Wait()
}



func getIP(ctx context.Context, wg *sync.WaitGroup) (ip string, err error) {
	go func() {
		select {
		case <-ctx.Done():
			err := ctx.Err()
			fmt.Println("协程取消", err)
			wg.Done()
			return
		}
	}()
	time.Sleep(4 * time.Second)
	fmt.Println("192.168.100.200")
	return
}
